package com.client;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;

import com.shared.SystemMsg;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;

/**
 * This is the main Activity of the Strangeroid client.
 * @author jiafanz
 *
 */
public class MainActivity extends Activity 
{
    private TextView                textView1;
    private EditText                editText1;
    
    // send button
    private Button                  button1;
    
    // start, disconnect button
    private Button                  button2;

    // the socket connecting us to the server 
    private Socket                  socket;

    // the streams we communicate to the server.
    private DataOutputStream        dout;
    private DataInputStream         din;
    private AlertDialog.Builder     builder;
    private ScrollView              scroll;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        textView1 = (TextView)findViewById(R.id.TextView01);
        editText1 = (EditText)findViewById(R.id.EditText01);
        button1 = (Button)findViewById(R.id.Button01);
        button1.setOnClickListener(new SendButtonListener());
        button2 = (Button)findViewById(R.id.Button02);
        button2.setOnClickListener(new StartDisconnectButtonListener());
        
        // by default, we will hide edittext and disable button1
        editText1.setVisibility(View.INVISIBLE);
        button1.setEnabled(false);
        
        
        scroll = (ScrollView)findViewById(R.id.ScrollView01);
        
        configureQuitDialog();
    }
    
    /**
     * Override the default back key behaviour, in order to pop out a dialog.
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) 
    {
        if (keyCode == KeyEvent.KEYCODE_BACK) 
        {
            AlertDialog alert = builder.create();
            alert.show();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    
    /**
     * Configure the Quit dialog to exit this application.
     */
    private void configureQuitDialog()
    {
        // configure a dialog.
        builder = new AlertDialog.Builder(this);
        builder.setTitle("Quit");
        builder.setMessage("Are you sure you want to exit?");
        builder.setCancelable(false);
        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() 
        {
            public void onClick(DialogInterface dialog, int id) 
            {
                // terminate
                try
                {
                    // send disconnect message to server
                    dout.writeUTF(SystemMsg.Disconnected.toString());
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
                
                MainActivity.this.finish();
            }
        });
        builder.setNegativeButton("No", new DialogInterface.OnClickListener() 
        {
            public void onClick(DialogInterface dialog, int id) 
            {
                dialog.cancel();
            }
        });
    }
    
    /**
     * This is an interception method. It will be invoked when the menu button
     * is clicked on the cell phone.
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        menu.add(0, 1, 1, R.string.exit_button);
        menu.add(0, 2, 2, R.string.about_button);

        return super.onCreateOptionsMenu(menu);
    }

    /**
     * Invoked when a particular menu item is selected
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        if (item.getItemId() == 1)
        {
            AlertDialog alert = builder.create();
            alert.show();
        }
        else if (item.getItemId() == 2)
        {
            // display the AboutDiaglogActivity
            Intent intent = new Intent();
            intent.setClass(MainActivity.this, AboutDialogActivity.class);
            startActivity(intent);
        }

        return super.onOptionsItemSelected(item);
    }
    
    /**
     * Updating the User Interface, in particular the text for displaying
     * the chat message.
     * @param str
     */
    private void updateUI(final String str)
    {
        textView1.append(str);
        scroll.smoothScrollTo(0, scroll.getBottom());
    }
    
    
    /**
     * This is the handler that is used to update the UI.
     */
    final Handler myHandler = new Handler()
    {
        public void handleMessage(Message msg)
        {
            // System.out.println((String)msg.obj);
            updateUI((String)msg.obj);
            
            int enableTextViews = msg.arg1;
            
            if (enableTextViews == 0)
            {
                editText1.setVisibility(View.VISIBLE);
                button1.setEnabled(true);
                button2.setEnabled(true);
            }
            else if (enableTextViews == 1)
            {
                editText1.setVisibility(View.INVISIBLE);
                button1.setEnabled(false);
                button2.setEnabled(true);
                button2.setText(R.string.start_button);
            }
            else if (enableTextViews == 2)
            {
                editText1.setVisibility(View.INVISIBLE);
                button1.setEnabled(false);
                button2.setEnabled(false);
            }
        }
    };

    /**
     * This class represents the thread that is listening on the message
     * sent from the server.
     * @author jiafanz
     *
     */
    class MyThread extends Thread
    {
        /**
         * Background thread runs this, show messages from other window
         */
        public void run()
        {
            try
            {
                while (true)
                {
                    Message msg = myHandler.obtainMessage();
                    String message = din.readUTF();
                    
                    String targetMsg;
                    
                    msg.arg1 = 0;
                    
                    if (message.equalsIgnoreCase(SystemMsg.Connected.toString()))
                    {
                        targetMsg = "Connected to the chat server...\n";
                    }
                    else if (message.equalsIgnoreCase(SystemMsg.Disconnected.toString()))
                    {
                        targetMsg = "Disconnected to the chat server...\n";
                        msg.arg1 = 1;
                    }
                    else if (message.equalsIgnoreCase(SystemMsg.NoPair.toString()))
                    {
                        targetMsg = "You are connected, no stranger found yet.\n";
                        msg.arg1 = 2;
                    }
                    else if (message.equalsIgnoreCase(SystemMsg.Serviced.toString()))
                    {
                        targetMsg= "You are connected to a stranger now say hi...\n";
                    }
                    else
                    {
                        targetMsg = "Stranger: " + message + "\n";
                    }
                    
                    msg.obj = targetMsg;
                    myHandler.sendMessage(msg);
                }
            }
            catch (EOFException ie)
            {
                // we don't need an error message for this
                // JIAFANZ: check the reason for this.
            }
            catch (IOException ie)
            {
                ie.printStackTrace();
            }
        }
    }

    /**
     * Send button event handler.
     * @author jiafanz
     *
     */
    class SendButtonListener implements OnClickListener
    {
        public void onClick(View v)
        {
            processMessage(editText1.getText().toString());
        }   
    }
    
    /**
     * Start or disconnect button handler.
     * @author jiafanz
     *
     */
    class StartDisconnectButtonListener implements OnClickListener
    {
        public void onClick(View v)
        {
            if (button2.getText().equals("start"))
            {
                // connect to the server
                try
                {
                    // Initiate the connection
                    // JIAFANZ: make this configurable
                    // CHANGE THE IP ADDRESS.
                    socket = new Socket("zhous.net", 5000);

                    // we got a connection, tell the world
                    System.out.println("connected to " + socket);

                    // create data input/output streams
                    din = new DataInputStream(socket.getInputStream());
                    dout = new DataOutputStream(socket.getOutputStream());

                    // start a background thread for receiving messages
                    new MyThread().start();
                }
                catch (IOException ie)
                {
                    ie.printStackTrace();
                }
                
                button2.setText(R.string.disconnect_button);
            }
            else // means disconnecting
            {
                try
                {
                    // send disconnect message to server
                    dout.writeUTF(SystemMsg.Disconnected.toString());
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
                
                button2.setText(R.string.start_button);
            }
        }
    }

    /**
     * Gets called when the user types something.
     * @param message
     */
    private void processMessage(String message)
    {
        try
        {
            textView1.append("You: " + message + "\n");
            // send it to the server
            dout.writeUTF(message);

            // clear out text input field
            editText1.setText("");
        }
        catch (EOFException ie)
        {
            // we don't need an error message for this
            // JIAFANZ: check the reason for this.
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
}